package in.co.codedoc.util;

import java.util.HashMap;

public class HexUtil
{
	public static String PrintHexDigits(byte[] data)
	{
		return PrintHexDigits(new StringBuffer(),data).toString();
	}
	
	public static StringBuffer PrintHexDigits(StringBuffer buffer,byte[] data)
	{
		for(byte b:data)
		{
			byte hh = (byte)((b&0x000000F0)>>4);
			byte lh = (byte)((b&0x0000000F));
			PrintHexDigitsImpl(buffer,hh);
			PrintHexDigitsImpl(buffer,lh);
		}
		return buffer;
	}

	public static StringBuffer PrintHexDigits(StringBuffer buffer,byte number)
	{
		byte hh = (byte)((number&0x000000F0)>>4);
		byte lh = (byte)((number&0x0000000F));
		PrintHexDigitsImpl(buffer,hh);
		PrintHexDigitsImpl(buffer,lh);
		return buffer;
	}

	private static StringBuffer PrintHexDigitsImpl(StringBuffer buffer,byte number)
	{
		return buffer.append(hexDigitByValue.get(number));
	}
		
	public static StringBuffer PrintHexDigits(StringBuffer buffer,int number)
	{
		if(number < 0)
		{
			throw new RuntimeException("Negative numbers not supported.");
		}
		
		byte digit = (byte)(number % 16);

		number = number/16;
		if(number > 0)
		{
			PrintHexDigits(buffer,number);
		}
		
		return buffer.append(hexDigitByValue.get(digit));
	}
	
	public static char DecodeHexDigits(char[] chars,int startIndex)
	{
		Byte upperByte= valueByHexDigit.get(Character.toLowerCase(chars[startIndex]));
		Byte lowerByte = valueByHexDigit.get(Character.toLowerCase(chars[startIndex+1]));
		
		if((upperByte == null) || (lowerByte == null))
		{
			throw new IllegalArgumentException();
		}
		
		return (char)(((upperByte) * 16) + lowerByte); 
	}
	
	private static HashMap<Byte, Character> hexDigitByValue = new HashMap<Byte, Character>();
	static
	{
		hexDigitByValue.put((byte)0, '0');
		hexDigitByValue.put((byte)1, '1');
		hexDigitByValue.put((byte)2, '2');
		hexDigitByValue.put((byte)3, '3');
		hexDigitByValue.put((byte)4, '4');
		hexDigitByValue.put((byte)5, '5');
		hexDigitByValue.put((byte)6, '6');
		hexDigitByValue.put((byte)7, '7');
		hexDigitByValue.put((byte)8, '8');
		hexDigitByValue.put((byte)9, '9');
		hexDigitByValue.put((byte)10, 'a');
		hexDigitByValue.put((byte)11, 'b');
		hexDigitByValue.put((byte)12, 'c');
		hexDigitByValue.put((byte)13, 'd');
		hexDigitByValue.put((byte)14, 'e');
		hexDigitByValue.put((byte)15, 'f');
	}
	private static HashMap<Character,Byte> valueByHexDigit = new HashMap<Character,Byte>();
	static
	{
		valueByHexDigit.put('0',(byte)0);
		valueByHexDigit.put('1',(byte)1);
		valueByHexDigit.put('2',(byte)2);
		valueByHexDigit.put('3',(byte)3);
		valueByHexDigit.put('4',(byte)4);
		valueByHexDigit.put('5',(byte)5);
		valueByHexDigit.put('6',(byte)6);
		valueByHexDigit.put('7',(byte)7);
		valueByHexDigit.put('8',(byte)8);
		valueByHexDigit.put('9',(byte)9);
		valueByHexDigit.put('a',(byte)10);
		valueByHexDigit.put('b',(byte)11);
		valueByHexDigit.put('c',(byte)12);
		valueByHexDigit.put('d',(byte)13);
		valueByHexDigit.put('e',(byte)14);
		valueByHexDigit.put('f',(byte)15);
	}
}
